package ig.finanzas;



import ig.util.ejb.IGBean;
import ig.util.ejb.IGEntityBean;
import ig.util.excepciones.DatoInvalidoExcepcion;
import ig.util.excepciones.LogicaExcepcion;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.naming.NamingException;



/**
 *
 * Implementa los metodos y el comportamiento de una tasa.
 *
 * @author  lfgarcia
 *
 */

public class TasaBean extends IGEntityBean implements Tasa{
    
    static final long serialVersionUID = 01;
    
    /**
     *
     * Nombre de la tasa
     *
     * @uml.property  name="nombre"
     *
     */
    
    private String nombre;
    
    /**
     *
     * Tipo de la tasa (SIMPLE o CURVA)
     *
     * @uml.property  name="tipo"
     *
     */
    
    private String tipo;
    
    /**
     *
     * Modalidad en que se encuentra expresada la tasa
     *
     * @uml.property  name="modalidadTasa"
     *
     * @uml.associationEnd
     *
     */
    
    private Modalidad modalidadTasa;
    
    /**
     *
     * @uml.property  name="valoresRegistrados"
     *
     * @uml.associationEnd
     *
     */
    
    private ManejadorValoresHistoricos valoresRegistrados;
    
    
    
    /**
     *
     * @return   Returns the nombre.
     *
     * @uml.property  name="nombre"
     *
     */
    
    public String getNombre(){
        
        return nombre;
        
    }
    
    
    
    /**
     *
     * @return   Returns the tipo.
     *
     * @uml.property  name="tipo"
     *
     */
    
    public String getTipo(){
        
        return tipo;
        
    }
    
    
    
    /**
     *
     * @return   Returns the modalidadTasa.
     *
     * @uml.property  name="modalidadTasa"
     *
     */
    
    public Modalidad getModalidadTasa(){
        
        return modalidadTasa;
        
    }
    
    
    
    /**
     *
     * Devuelve el valor vigente de la tasa a una determinada fecha.
     *
     * @param fecha
     *
     * @param numdias Este parametro se utiliza en caso de que la tasa sea una curva cero cupon.
     *
     * @return
     *
     * @throws DatoInvalidoExcepcion Si alguno de los parametros es invalido.
     *
     * @throws LogicaExcepcion Si no hay suficiente informacion para efectuar el calculo, o si el resultado es imaginario.
     *
     */
    
    public double obtenerValorVigenteA(Date fecha, int numdias) throws DatoInvalidoExcepcion, LogicaExcepcion{
        
        try {
            
            return valoresRegistrados.obtenerValorVigenteA(fecha, numdias);
            
        } catch (DatoInvalidoExcepcion e) {
            
            throw new DatoInvalidoExcepcion(e.toString()+" Error con la tasa + " + nombre +". ");
            
        } catch (LogicaExcepcion e) {
            
            throw new LogicaExcepcion(e.toString()+" Error con la tasa + " + nombre+ ". ");
            
        }
        
    }
    
    
    /**
     *
     * @param tipo   The tipo to set.
     *
     * @uml.property  name="tipo"
     *
     */
    
    private void setTipo(String tipo) throws DatoInvalidoExcepcion{
        
        //if (!tipo.equals(Tasa.TIPO_SIMPLE) && !tipo.equals(Tasa.TIPO_CURVA))
        /*
         * Cambio Hecho por Cristhiam Reina
         */
        if (!tipo.equals(Tasa.TIPO_SIMPLE) && !tipo.equals(Tasa.TIPO_CURVA) && !tipo.equals(Tasa.TIPO_PLAZOS)){
            
            throw new DatoInvalidoExcepcion("El tipo especificado para la tasa " + nombre + "no es valido");
            
        }
        
        this.tipo = tipo;
        
    }
    
    
    
    /**
     *
     * Devuelve el cambio esperado en la serie de valores calculado a partir de la forma en que lo
     *
     * especifique el DefinidorCalculoCambioEsperado.
     *
     * @param fecha
     *
     * @param definidor
     *
     * @return
     *
     * @throws DatoInvalidoExcepcion Si alguno de los parametros recibidos es invalido.
     *
     * @throws LogicaExcepcion Si la forma de calculo no permite obtener el valor, si no hay suficientes
     *
     * valores en la serie, si la informacion hallada no alcanza a ser una muestra estadisticamente representativa,
     *
     * o si la serie no permite el calculo utilizando diferencias logaritmicas.
     *
     */
    
    public double cambioEsperadoValoresRegistrados(Date fecha, DefinidorCalculoCambioEsperado definidor) throws DatoInvalidoExcepcion, LogicaExcepcion{
        
        try {
            
            return valoresRegistrados.cambioEsperado(fecha, definidor,false);
            
        } catch (DatoInvalidoExcepcion e) {
            
            throw new DatoInvalidoExcepcion(e.toString()+" Error con la tasa + " + nombre +". ");
            
        } catch (LogicaExcepcion e) {
            
            throw new LogicaExcepcion(e.toString()+" Error con la tasa + " + nombre+ ". ");
            
        }
        
    }
    
    
    
    public void eliminarEntidad(){}
    
    
    
    public void actualizarEntidad(){}
    
    
    
    public void cargarEntidad() throws NamingException, DatoInvalidoExcepcion, SQLException{
        ResultSet rs2 =null;
        ResultSet rs =null;
        try {
            /*TasaPK tasaPK = (TasaPK)ctx.getPrimaryKey();
            this.nombre = tasaPK.getNombre();*/
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            pstmt1 = conn.prepareStatement(
                    "SELECT NOMBRE, TIPO, MODALIDADTASA, NOMINALMODALIDADTASA "+
                    "FROM TASAS "+
                    "WHERE ID=?");
            pstmt1.setLong(1, pk.getIdInterna());
            rs = pstmt1.executeQuery();
            rs.next();
            
            setTipo(rs.getString("TIPO"));
            if (tipo.equals(Tasa.TIPO_SIMPLE)){
                try {
                    this.valoresRegistrados = new MVHSimple();
                } catch (DatoInvalidoExcepcion e) {}
            }else{
                try {
                    this.valoresRegistrados = new MVHCurvaCupon();
                } catch (DatoInvalidoExcepcion e) {}
            }
            
            String modalidadtasa=rs.getString("MODALIDADTASA");
            boolean nominal1 = ( rs.getInt("NOMINALMODALIDADTASA")==1?true:false );
            this.modalidadTasa = new Modalidad(modalidadtasa, nominal1);
            try {pstmt1.close();} catch (Exception e) {}
            pstmt1 = conn.prepareStatement(
                    "SELECT DISTINCT FECHA AS FECHAS "+
                    "FROM VALORESTASAS "+
                    "WHERE IDTASA=? ");
            pstmt1.setLong(1, pk.getIdInterna());
            try {rs.close();} catch (Exception e) {}
            rs = pstmt1.executeQuery();

            try {pstmt2.close();} catch (Exception e) {}
            pstmt2 = conn.prepareStatement(
                    "SELECT POSICION, VALOR "+
                    "FROM VALORESTASAS "+
                    "WHERE IDTASA=? AND FECHA=? " +
                    "ORDER BY POSICION");
            
            while (rs.next()) {
                java.sql.Date fecha = rs.getDate("FECHAS");
                pstmt2.setLong(1, pk.getIdInterna());
                pstmt2.setDate(2, fecha);
                rs2 = pstmt2.executeQuery();

                /*
                 * Modificado por Cristhiam Reina
                 * Modificado el 18/07/2011
                 */
                /*double[] valor;
                 if (tipo.equals(Tasa.TIPO_SIMPLE))
                 valor = new double[1];
                 else
                 valor = new double[4];
                 int i=0;
                 while (rs2.next()){
                 valor[i]=rs2.getDouble("VALOR");
                 i++;
                 }
                 valoresRegistrados.adicionarValor(fecha, valor);*/
                List<double[]> vec = new ArrayList<double[]>();
                while (rs2.next()) {
                    /*valor[i]=rs2.getDouble("VALOR");
                     i++;*/
                    double[] arr = new double[2];
                    arr[0] = rs2.getDouble("POSICION");
                    arr[1] = rs2.getDouble("VALOR");
                    vec.add(arr);
                }

                if (tipo.equals(Tasa.TIPO_SIMPLE)) {
                    try {
                        this.valoresRegistrados = new MVHSimple();
                    } catch (DatoInvalidoExcepcion e) {
                    }
                } else if (tipo.equals(Tasa.TIPO_CURVA)) {
                    try {
                        this.valoresRegistrados = new MVHCurvaCupon();
                    } catch (DatoInvalidoExcepcion e) {
                    }
                } else {
                    try {
                        this.valoresRegistrados = new MVHCurvaCupon(vec.size());
                    } catch (DatoInvalidoExcepcion e) {
                    }
                }

                if (!tipo.equals(Tasa.TIPO_PLAZOS)) {
                    int i = 0;
                    double[] valor = new double[vec.size()];
                    for (double[] va : vec) {
                        valor[i] = va[1];
                        i++;
                    }
                    //El error
                    valoresRegistrados.adicionarValor(fecha, valor);
                } else {
                    int i = 0;
                    double[][] valor = new double[vec.size()][2];

                    for (double[] va : vec) {
                        valor[i][0] = va[0];
                        valor[i][1] = va[1];
                        i++;
                    }

                    valoresRegistrados.adicionarValorArr2(fecha, valor);
                }
                pstmt2.clearParameters();
                try {
                    rs2.close();
                } catch (Exception e) {
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        } catch (DatoInvalidoExcepcion e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new DatoInvalidoExcepcion(e.toString());
        }finally{
            //try {conn.close();} catch (Exception e) {}   
            try {pstmt2.close();} catch (Exception e) {}
            try {pstmt1.close();} catch (Exception e) {}
            try {rs.close();} catch (Exception e) {}   
            try {rs2.close();} catch (Exception e) {}   
        }
    }
    
        public TasaBean ejbFindByPrimaryKey(TasaPK key) throws Exception{
        ResultSet rs =null;
        try{
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");            
            pstmt1 = conn.prepareStatement(                    
                    "SELECT ID, NOMBRE " +                    
                    "FROM TASAS " +                    
                    "WHERE NOMBRE=?");            
            pstmt1.setString(1, key.getNombre().trim());            
            rs = pstmt1.executeQuery();
            if (!rs.next())
                throw new Exception("No fue posible encontrar la tasa " + key);
            
            this.nombre = rs.getString("NOMBRE");
            this.pk = new TasaPK(nombre);
            this.pk.setIdInterna(rs.getLong("ID"));
            try {pstmt1.close();pstmt1=null;} catch (Exception e) {}
            cargarEntidad();
            return this;
        }catch(Exception e){
            throw new Exception("No fue posible encontrar la tasa " + key);
        }finally{
            try {pstmt1.close();} catch (Exception e) {}
            //try {conn.close();} catch (SQLException e) {}
            try {rs.close();} catch (Exception e) {}
        }
    }
    public Collection ejbFindAll() throws Exception {
        ArrayList tasas = new ArrayList();
        ResultSet rs = null;
        try {
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            pstmt1 = conn.prepareStatement( "SELECT ID,NOMBRE FROM TASAS");
            rs = pstmt1.executeQuery();
            while (rs.next()) {
                TasaPK key=new TasaPK(rs.getString("NOMBRE"));
                key.setIdInterna(rs.getInt("ID"));
                tasas.add(key);
            }
        } catch (Exception e) {
            throw new Exception(e.toString());
        } finally {
            try {
                pstmt1.close();
            } catch (SQLException e) {
            }
//            try {
//                conn.close();
//            } catch (SQLException e) {
//            }
            try {
                rs.close();
            } catch (SQLException e) {
            }
        }
        return tasas;
    }
    /*
     * Creado por Cristhiam Reina
     * Creado el 18/07/2011
     */

    public double obtenerValorVigentePlazoA(Date fecha, int numdias) throws DatoInvalidoExcepcion, LogicaExcepcion{

        try {

            return valoresRegistrados.obtenerValorVigentePlazoA(fecha, numdias);

        } catch (DatoInvalidoExcepcion e) {

            throw new DatoInvalidoExcepcion(e.toString()+" Error con la tasa + " + nombre +". ");

        } catch (LogicaExcepcion e) {

            throw new LogicaExcepcion(e.toString()+" Error con la tasa + " + nombre+ ". ");

        }

    }
}

